/**
 * 柯理化函数的使用最直白的方法是调用另一个函数并为它传入要柯里化的函数和必要的参数.
 */


// 高级程序设计上的通用例子
function curry (fn) {
  // 获取剩余参数 将类数组转化成数组
  var args = Array.prototype.slice.call(arguments, 1);
  return function () {
    var innerArgs = Array.prototype.slice.call(arguments);
    var finalArgs = args.concat(innerArgs);
    return fn.apply(null, finalArgs);
  }
}
function add (num1, num2) {
  return num1 * num2;
}
var curriedAdd = curry(add, 5);
// alert(curriedAdd(3)); // 8
console.log("curriedAdd(3)", curriedAdd(3));
/** 缺陷：上面方法不支持参数调用的方法: curriedAdd(3)(4)(5) */



/** ES6 方法 简单明了 */

let myCurry = (a)=>(b)=>a+b

console.log("ES6 => myCurry", myCurry(2)(3));



/** 支持链式调用并且可以多个 */


const addReduce = (...arg)=>{
  console.log("addReduce",arg);
  if (arg.length>0){
    let ans = arg.reduce((tatol,cur)=>{
      return tatol+cur
    })
    return ans
  }else{// 预防不传参情况
    return []
  }
}

let all = []
function  sum(...args) {
  if(args.length==0){
    console.log("是否执行至此", args,all);
    return addReduce.apply(null,all)
  }else{
    all.push(...args)
    console.log('args', args,'all',all);
    return sum
  }
}
/**
 * 思路：要执行函数后面多个参数，就要把每次的参数存起来，后面调用累加器
 * 注意：最后面要执行方法，不能返回一个函数，要将方法执行就要立即执行，加上一个 ()
 */

console.log("sum", sum(2)(3,4)(5)())//()(5)(6));

function bestCurry(fn,...arg) {
  let argument = arg || []
  return function sum2(...moreArg) {
    console.log("moreArg", moreArg);
    let args = argument
    if (moreArg.length==0){
      return fn.apply(null,args)
    }else{
      argument.push(...moreArg)
      return sum2
    }
  }
}


const test = bestCurry(addReduce,0)

console.log("test", test(1)(2)(3)(4)());


function curry (func) {
  return function curried (...args) {
    // 关键知识点：function.length 用来获取函数的形参个数
    // 补充：arguments.length 获取的是实参个数
    if (args.length >= func.length) {
      return func.apply(this, args)
    }
    return function (...args2) {
      return curried.apply(this, args.concat(args2))
    }
  }
}

// 测试
function sum (a, b, c) {
  return a + b + c
}
const curriedSum = curry(sum)

console.log(curriedSum(1, 2, 3))
console.log(curriedSum(1)(2, 3))
console.log(curriedSum(1)(2)(3))
